// Fill out your copyright notice in the Description page of Project Settings.


#include "SPakAssetsView.h"
#include "SlateOptMacros.h"
#include "SPakAssetRow.h"
#include "HotPakerFileLib.h"
#include "AssetData.h"

#define LOCTEXT_NAMESPACE "SPakAssetsView"

BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SPakAssetsView::Construct(const FArguments& InArgs)
{

	ChildSlot
		[
			SNew(SVerticalBox)
			+ SVerticalBox::Slot()
		.AutoHeight()
		.MaxHeight(256.0f)
		[
			SAssignNew(AssetViewTree, SAssetsViewTree)
			.HeaderRow(
				SNew(SHeaderRow)
				//.Visibility(EVisibility::Collapsed)

				+ SHeaderRow::Column("AssetName")
				.DefaultLabel(LOCTEXT("AssetNameColumnHeader", "Asset"))
				.FillWidth(1.0f)

				+ SHeaderRow::Column("GuidName")
				.DefaultLabel(LOCTEXT("GuidNameColumnHeader", "Guid"))
				.FillWidth(1.0f)

				+ SHeaderRow::Column("ChunkName")
				.DefaultLabel(LOCTEXT("ChunkNameColumnHeader", "ChunkIDs"))
				.FillWidth(1.0f)
			)
		.OnGenerateRow(this, &SPakAssetsView::HandleAssetViewGenerateRow)
		.OnGetChildren(this, &SPakAssetsView::HandleAssetViewGetChildren)
		.ItemHeight(16.f)
		.TreeItemsSource(&AssetList)
		.SelectionMode(ESelectionMode::Single)
		]
		];

}



END_SLATE_FUNCTION_BUILD_OPTIMIZATION


void SPakAssetsView::AssignAssetList(TArray<FAssetData> AssetDatas)
{
	AssetList.Reset();
	SelectAssets.Reset();

	for (auto AssetData : AssetDatas)
	{
		FAssetDetailNode_Ref RootAssetNode = MakeShareable(new FAssetDetailNode);
		RootAssetNode->PackageName = AssetData.PackageName;
		RootAssetNode->Guid = UHotPakerFileLib::GetAssetPackageDataByPackageName(AssetData.PackageName)->PackageGuid.ToString();
		RootAssetNode->ChunkIDs = AssetData.ChunkIDs;
		for (int i = 0; i < AssetData.ChunkIDs.Num(); ++i)
		{
			RootAssetNode->Chunks += i == 0 ? FString::Printf(TEXT("%d"), AssetData.ChunkIDs[i]) : FString::Printf(TEXT("_%d"), AssetData.ChunkIDs[i]);
		}
		AssetList.Add(RootAssetNode);
		SelectAssets.Add(AssetData.PackageName);
	}

	AssetViewTree->RequestTreeRefresh();

	SelectAssetsChangeDelegate.ExecuteIfBound(SelectAssets);
}


TSharedRef<ITableRow> SPakAssetsView::HandleAssetViewGenerateRow(FAssetDetailNode_Ref AssetDetailNode, const TSharedRef<STableViewBase>& OwnerTable)
{
	return SNew(SPakAssetRow, this)
		.AssetDetailNode(AssetDetailNode)
		.OwnerTableView(OwnerTable);
}

void SPakAssetsView::HandleAssetViewGetChildren(FAssetDetailNode_Ref AssetDetailNode, TArray<FAssetDetailNode_Ref>& OutDependencies)
{

	TArray<FName> DependentAssets = UHotPakerFileLib::GetAssetDependencies(AssetDetailNode->PackageName);

	for (auto DependentAsset : DependentAssets)
	{
		if (AssetDetailNode->DependenceAssets.Contains(DependentAsset) || AssetDetailNode->PackageName.IsEqual(DependentAsset))
			continue;
		FAssetData AssetData;
		if (UHotPakerFileLib::GetAssetDataByPackageName(DependentAsset, AssetData))
		{
			FAssetDetailNode_Ref DependenceAssetNode = MakeShareable(new FAssetDetailNode);
			DependenceAssetNode->PackageName = DependentAsset;
			DependenceAssetNode->Guid = UHotPakerFileLib::GetAssetPackageDataByPackageName(DependentAsset)->PackageGuid.ToString();
			DependenceAssetNode->ChunkIDs = AssetData.ChunkIDs;
			for (int i = 0; i < AssetData.ChunkIDs.Num(); ++i)
			{
				DependenceAssetNode->Chunks += i == 0 ? FString::Printf(TEXT("%d"), AssetData.ChunkIDs[i]) : FString::Printf(TEXT("_%d"), AssetData.ChunkIDs[i]);
			}
			AssetDetailNode->DependenceAssets.Add(DependentAsset, DependenceAssetNode);
		}
	}

	AssetDetailNode->DependenceAssets.GenerateValueArray(OutDependencies);
}

const TArray<FName>& SPakAssetsView::GetAllSelectAssets()
{
	return SelectAssets;
}

void SPakAssetsView::AddSelectAsset(const FName& InPackageName)
{
	if (!SelectAssets.Contains(InPackageName))
		SelectAssets.Add(InPackageName);

	SelectAssetsChangeDelegate.ExecuteIfBound(SelectAssets);
}

void SPakAssetsView::RemoveSelectAsset(const FName& InPackageName)
{
	if (SelectAssets.Contains(InPackageName))
		SelectAssets.Remove(InPackageName);

	SelectAssetsChangeDelegate.ExecuteIfBound(SelectAssets);
}

bool SPakAssetsView::IsDependenceSelected(const FName& InPackageName)
{
	if (SelectAssets.Contains(InPackageName))
	{
		TArray<FName> DependentAssets = UHotPakerFileLib::GetAssetDependencies(InPackageName);

		if (DependentAssets.Num() == 0)
			return false;

		for (auto DependentAsset : DependentAssets)
		{
			if (!SelectAssets.Contains(DependentAsset))
				return false;
		}
		return true;
	}
	return false;
}

FReply SPakAssetsView::SelectAllAssets()
{
	TArray<FName> RootPackageNames;
	for (auto Asset : AssetList)
		RootPackageNames.Add(Asset->PackageName);
	SelectAssets.Reset();
	UHotPakerFileLib::GetAssetsAllDependencies(RootPackageNames, SelectAssets);
	SelectAssetsChangeDelegate.ExecuteIfBound(SelectAssets);
	return FReply::Handled();
}

FReply SPakAssetsView::SelectRootAssets()
{
	SelectAssets.Reset();
	for (auto Asset : AssetList)
		SelectAssets.Add(Asset->PackageName);
	SelectAssetsChangeDelegate.ExecuteIfBound(SelectAssets);
	return FReply::Handled();
}

FReply SPakAssetsView::ClearSelectAssets()
{
	SelectAssets.Reset();
	SelectAssetsChangeDelegate.ExecuteIfBound(SelectAssets);
	return FReply::Handled();
}


bool SPakAssetsView::IsReferencedByOtherAsset(FName PackageName)
{
	for (auto AssetDetailNode : AssetList)
	{
		if (AssetDetailNode->PackageName.IsEqual(PackageName))
			return true;
		for (auto DependenceAsset : AssetDetailNode->DependenceAssets)
			return IsReferencedByOtherAsset(DependenceAsset.Value->PackageName);
	}
	return false;
}

#undef LOCTEXT_NAMESPACE
